// ==========================================================
// matrix_keypad.v — 4×4矩阵键盘扫描模块
// 输入：Key_Col[3:0] （列输入）
// 输出：Key_Row[3:0] （行为低有效）
// 输出：key_state[15:0] （1=未按，0=按下）
// 适用于50 MHz时钟；含约5 ms消抖
// ==========================================================
module matrix_keypad #(
    parameter CLK_HZ = 50_000_000
)(
    input  wire        clk,
    input  wire        rst_n,
    output reg  [3:0]  Key_Row,     // 行输出（低有效）
    input  wire [3:0]  Key_Col,     // 列输入
    output reg  [15:0] key_state    // 当前稳定键状态
);
    // 扫描时基：约1 kHz（每行1 ms）
    localparam integer SCAN_DIV = CLK_HZ / 1000;
    reg [15:0] divcnt;
    reg scan_en;

    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            divcnt <= 0;
            scan_en <= 1'b0;
        end else if(divcnt == SCAN_DIV-1) begin
            divcnt <= 0;
            scan_en <= 1'b1;
        end else begin
            divcnt <= divcnt + 1;
            scan_en <= 1'b0;
        end
    end

    // 行扫描指针
    reg [1:0] row_idx;
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)
            row_idx <= 2'd0;
        else if(scan_en)
            row_idx <= row_idx + 2'd1;
    end

    // 根据当前行输出驱动
    always @(*) begin
        case(row_idx)
            2'd0: Key_Row = 4'b1110;
            2'd1: Key_Row = 4'b1101;
            2'd2: Key_Row = 4'b1011;
            2'd3: Key_Row = 4'b0111;
            default: Key_Row = 4'b1111;
        endcase
    end

    // 原始扫描结果寄存
    reg [15:0] key_raw;
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)
            key_raw <= 16'hFFFF;
        else if(scan_en) begin
            // 每次扫描一行
            key_raw[row_idx*4 +:4] <= Key_Col;
        end
    end

    // 消抖：连续稳定N次才更新
    localparam integer DEBOUNCE_CNT_MAX = 5; // 约5 ms
    reg [3:0] stable_cnt [15:0];
    integer i;
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            key_state <= 16'hFFFF;
            for(i=0;i<16;i=i+1)
                stable_cnt[i] <= 0;
        end else if(scan_en) begin
            for(i=0;i<16;i=i+1) begin
                if(key_raw[i] == key_state[i])
                    stable_cnt[i] <= 0; // 与上次一致，计数清零
                else if(stable_cnt[i] < DEBOUNCE_CNT_MAX)
                    stable_cnt[i] <= stable_cnt[i] + 1'b1;
                else begin
                    stable_cnt[i] <= 0;
                    key_state[i]  <= key_raw[i]; // 更新稳定值
                end
            end
        end
    end
endmodule
